/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stddef.h>
#include "securec.h"
#include "ola_log.h"
#include "ola_pal_os.h"
#include "ola_error.h"
#include "ola_base_utils.h"
#include "ola_timer.h"


static unsigned long long g_lastProcTime = 0;
static OlaTimer g_OlaTimerList[OLA_MAX_TIMER];

int OlaInitTimer(void)
{
    if (OlaGetTime(&g_lastProcTime) == OLA_ERROR) {
        return OLA_OS_ERR_GET_TIME;
    }
    (void)memset_s(g_OlaTimerList, sizeof(g_OlaTimerList), 0, sizeof(g_OlaTimerList));
    return OLA_OK;
}

void OlaDeinitTimer(void)
{
    (void)memset_s(g_OlaTimerList, sizeof(g_OlaTimerList), 0, sizeof(g_OlaTimerList));
}

int OlaStartTimer(const OlaTimer *timer, OlaTimerEnum timerId)
{
    if ((timer == NULL) || (timerId >= OLA_MAX_TIMER)) {
        OlaLogWarning("invalid params.");
        return OLA_COM_ERR_INVALID_ARGUMENT;
    }

    /* g_OlaTimerList在Init时已经初始化，不会为空 */
    OlaTimer *olaTimer = &g_OlaTimerList[timerId];
    olaTimer->timerCallback = timer->timerCallback;
    olaTimer->context = timer->context;
    olaTimer->timeoutMs = timer->timeoutMs;
    return OLA_OK;
}

int OlaStopTimer(OlaTimerEnum timerId)
{
    if (timerId >= OLA_MAX_TIMER) {
        OlaLogWarning("invalid params.");
        return OLA_COM_ERR_INVALID_ARGUMENT;
    }

    /* g_OlaTimerList在Init时已经初始化，不会为空 */
    OlaTimer *olaTimer = &g_OlaTimerList[timerId];
    olaTimer->timeoutMs = 0;
    return OLA_OK;
}

int OlaGetTimerStatus(OlaTimerEnum timerId)
{
    if (g_OlaTimerList[timerId].timeoutMs == 0) {
        return TIMER_CLOSED;
    }
    return TIMER_OPENED;
}

int OlaTimerProcess(void)
{
    unsigned long long curTime = 0;
    unsigned long long slipTime;
    OlaTimer *olaTimer = NULL;

    if (OlaGetTime(&curTime) == OLA_ERROR) {
        return OLA_OS_ERR_GET_TIME;
    }

    slipTime = OlaDeltaTime(curTime, g_lastProcTime);
    g_lastProcTime = curTime;
    if (slipTime == 0) {
        return OLA_OK;
    }

    /* g_OlaTimerList在Init时已经初始化，不会为空 */
    olaTimer = &g_OlaTimerList[0];

    unsigned int n;
    for (n = 0; n < OLA_MAX_TIMER; n++, olaTimer++) {
        if (olaTimer->timeoutMs == 0) {
            continue;
        }

        if (olaTimer->timeoutMs > slipTime) {
            olaTimer->timeoutMs -= slipTime;
        } else {
            olaTimer->timeoutMs = 0;
            if (olaTimer->timerCallback != NULL) {
                (*olaTimer->timerCallback)(olaTimer->context);
            }
        }
    }

    return OLA_OK;
}
